LibChecker 权限体验优化

出息了,给 6.1K start 的 LibChecker提交代码

https://github.com/LibChecker/LibChecker/pull/1783

先看效果

修复前:

修复后:

修复说明

问题现状

  1. 如果用户第一次未授予 已安装应用列表 权限,那么用户就没有办法再在 app 内调起权限授予窗
  2. 即使在设置选项中开启了相应权限,再重新回到 app,也没有继续下一步扫描应用,需要强制关闭 app 后重新打开才会继续扫描

问题修复

  1. 未获取权限的情况下,加个按钮去申请 已安装应用列表 权限
  2. 任何情况授予权限后,自动执行读取应用

背景与问题

在国内上架应用时,监管部门要求开发者获取 GET_INSTALLED_APPS权限才能读取已安装应用列表,否则将无法提供完整的应用信息。LibChecker 早期版本没有为该权限设计合理的申请流程:

这些问题不仅违背了工信部合规要求,也导致了不良的用户体验,需要在代码层面进行修复。

改动内容

此次 PR 的核心改动可分为四点:

1. 常量声明

Constants.kt 中新增了 GET_INSTALLED_APPS 字符串常量,用于引用系统权限名称 patch-diff.githubusercontent.com

// Constants.kt
const val GET_INSTALLED_APPS = "com.android.permission.GET_INSTALLED_APPS"

2. AppListFragment:注册权限请求并在拒绝页触发

这一系列改动保证了用户点击按钮时能看到系统权限弹窗,并在授权成功后立即回调业务逻辑。

3. HomeViewModel:新增状态标记

HomeViewModel 中增加了 checkPackagesPermission 布尔变量。它用于标记当前是否需要在 Activity 恢复时重新检查权限,避免在未申请或未授权情况下无意义地调用初始化逻辑。

4. MainActivity:在 onResume 中重新检测并继续流程

MainActivityonResume() 方法中新增如下逻辑

override fun onResume() {
    super.onResume()
    if (appViewModel.checkPackagesPermission) {
        val granted = ContextCompat.checkSelfPermission(
            this,
            Constants.GET_INSTALLED_APPS
        ) == PackageManager.PERMISSION_GRANTED
        if (granted) {
            appViewModel.checkPackagesPermission = false
            appViewModel.initItems() // 重新加载应用列表
        }
    }
}

如果从系统设置返回时检测到用户已授权,则清除标记并重新初始化应用列表。这样即使用户离开应用去授权,也能获得无缝体验。

效果与意义

通过上述改造,LibChecker 的权限申请流程更加完善:

后续思考

这一改动只是合规性的开始。国内隐私规范日益严格,未来可能还会要求对“查询已安装应用列表”进行最小化采集或匿名化处理。在后续版本中,可以进一步结合隐私沙盒或动态权限分级策略,确保在满足功能需求的同时最大化地保护用户隐私。